#include <iostream>
#include <memory>
#include <string>
#include <vector>
#include <utility>

// 一个简单的类用于演示
class Resource {
private:
    std::string m_name_;
    size_t m_size_;

public:
    Resource(std::string name, size_t size)
        : m_name_(std::move(name)), m_size_(size) {
        std::cout << "  Resource构造: " << m_name_ << " (大小: " << m_size_ << ")\n";
    }

    ~Resource() {
        std::cout << "  Resource析构: " << m_name_ << "\n";
    }

    void use() const {
        std::cout << "  使用资源: " << m_name_ << " (大小: " << m_size_ << ")\n";
    }
};

// 一个带有参数的类
class Widget {
private:
    int m_id_;
    std::string m_name_;
    
public:
    Widget(int id, std::string name)
        : m_id_(id), m_name_(std::move(name)) {
        std::cout << "  Widget构造: ID=" << m_id_ << ", 名称=" << m_name_ << "\n";
    }
    
    ~Widget() {
        std::cout << "  Widget析构: ID=" << m_id_ << "\n";
    }
    
    void process() const {
        std::cout << "  处理Widget: ID=" << m_id_ << ", 名称=" << m_name_ << "\n";
    }
};

// 复杂的自定义删除器示例
struct FileDeleter {
    void operator()(FILE* file) const {
        if (file) {
            std::cout << "  关闭文件\n";
            fclose(file);
        }
    }
};

void demonstrate_smart_pointers() {
    std::cout << "  C++14 智能指针增强 (make_unique) 演示:\n\n";
    
    // 1. 基本用法 - make_unique的简单使用
    std::cout << "  1. 基本用法:\n";
    
    // C++11方式
    std::cout << "  C++11方式: std::unique_ptr<Resource> res1(new Resource(\"res1\", 100));\n";
    std::unique_ptr<Resource> res1(new Resource("res1", 100));
    res1->use();
    
    // C++14方式 - 使用make_unique
    std::cout << "  C++14方式: auto res2 = std::make_unique<Resource>(\"res2\", 200);\n";
    auto res2 = std::make_unique<Resource>("res2", 200);
    res2->use();
    std::cout << "\n";
    
    // 2. 数组支持
    std::cout << "  2. 数组支持:\n";
    std::cout << "  创建整数数组: auto arr = std::make_unique<int[]>(5);\n";
    auto arr = std::make_unique<int[]>(5);
    for (int i = 0; i < 5; ++i) {
        arr[i] = i * 10;
    }
    
    std::cout << "  数组内容: ";
    for (int i = 0; i < 5; ++i) {
        std::cout << arr[i] << " ";
    }
    std::cout << "\n\n";
    
    // 3. 安全性 - 避免内存泄漏
    std::cout << "  3. 安全性 - 避免内存泄漏:\n";
    std::cout << "  在函数调用中使用make_unique的好处:\n";
    std::cout << "  C++11: processWidget(std::unique_ptr<Widget>(new Widget(1, \"名称\")), calculatePriority());\n";
    std::cout << "  C++14: processWidget(std::make_unique<Widget>(1, \"名称\"), calculatePriority());\n";
    std::cout << "  C++14版本避免了可能的内存泄漏风险\n\n";
    
    // 4. make_unique与自定义删除器
    std::cout << "  4. 注意：make_unique不支持自定义删除器\n";
    std::cout << "  自定义删除器仍需使用构造函数方式:\n";
    
    {
        std::cout << "  std::unique_ptr<FILE, FileDeleter> file(fopen(\"temp.txt\", \"w\"));\n";
        std::unique_ptr<FILE, FileDeleter> file(fopen("temp.txt", "w"));
        if (file) {
            std::cout << "  文件已打开，写入数据\n";
            fprintf(file.get(), "测试数据");
        }
        // 文件会在作用域结束时自动关闭
    }
    std::cout << "\n";
    
    // 5. 使用场景
    std::cout << "  5. 常见使用场景:\n";
    
    // 工厂函数
    std::cout << "  工厂函数:\n";
    auto create_resource = [](const std::string& name, size_t size) {
        return std::make_unique<Resource>(name, size);
    };
    
    auto factory_resource = create_resource("factory_res", 300);
    factory_resource->use();
    
    // 容器中存储独占所有权的对象
    std::cout << "\n  在容器中存储unique_ptr:\n";
    std::vector<std::unique_ptr<Widget>> widgets;
    
    widgets.push_back(std::make_unique<Widget>(1, "Widget 1"));
    widgets.push_back(std::make_unique<Widget>(2, "Widget 2"));
    
    std::cout << "  访问容器中的对象:\n";
    for (const auto& widget : widgets) {
        widget->process();
    }
    
    std::cout << "\n  C++14 make_unique的优势:\n";
    std::cout << "  - 语法更简洁\n";
    std::cout << "  - 避免代码重复（DRY原则）\n";
    std::cout << "  - 提高异常安全性\n";
    std::cout << "  - 与make_shared保持一致的API风格\n";
    std::cout << "  - 避免在表达式求值顺序不确定时的内存泄漏风险\n";
} 